/* (C) C.D.F. Miller, Heriot-Watt University, March 1984
 *
 *	Permission is hereby given to reproduce or modify this
 *	software freely, provided that this notice be retained,
 *	and that no use be made of the software for commercial
 *	purposes without the express written permission of the
 *	author.
 */

#include        <err.h>
#include	<lbl.h>

void	printr(char, int, FILE *);
static void printd(int, FILE *);
static void printa(char, int, FILE *);
static void auxprinta(char, int, FILE *);

void
Label::print(FILE *out)
{
	format f = l_type->t_format;
	int i;

	for (i = 0; i <= l_bottom; i++) {
		while (*f) {
			if (*f != '%')
				putc(*f, out);
			else
				switch (*++f) {
				default:
					putc(*f, out);
					break;
				case '\0':
					putc('%', out);
					break;
				case '0':
					printd(l_levels[i] - 1, out);
					f++;
					goto loopend;
				case '1':
					printd(l_levels[i], out);
					f++;
					goto loopend;
				case 'i':
				case 'I':
					printr(*f, l_levels[i],
					       out);
					f++;
					goto loopend;
				case 'a':
				case 'A':
					printa(*f, l_levels[i],
					       out);
					f++;
					goto loopend;
				}
			f++;
		}
		warnx("%sformat too short to print label %s", maybe_loc(), l_name);
		break;
loopend:
		continue;
	}
}

/* Print Decimal */
void
printd(int n, FILE *out)
{
	fprintf(out, "%u", n);
}

/* Print Alphabetic
 *	actually base 26 (digits a-z), displaced by 1!
 *	a is either "a" or "A" for upper or lower case.
 */
void
printa(char a, int n, FILE *out)
{
	if (n == 0)
		putc('0', out);
	else
		auxprinta(a, n - 1, out);
}

void
auxprinta(char a, int n, FILE *out)
{
	if (n > 25)
		auxprinta(a, n / 26 - 1, out);
	putc((int)a + n % 26, out);
}

/* Print Roman
 *	a is either "a" or "A" for upper or lower case.
 */
void
printr(char a, int n, FILE *out)
{
	if (n == 0) {
		putc('0', out);
		return;
	}
	if (n >= 50000) {
		putc('!', out);
		return;
	}
	while (n >= 10000)
		putc(a + ('Z' - 'I'), out), n -= 10000;
	if (n >= 9000)
		putc(a + ('M' - 'I'), out), putc(a + ('Z' - 'I'), out), n -= 9000;
	if (n >= 5000)
		putc(a + ('W' - 'I'), out), n -= 5000;
	if (n >= 4000)
		putc(a + ('M' - 'I'), out), putc(a + ('W' - 'I'), out), n -= 4000;
	while (n >= 1000)
		putc(a + ('M' - 'I'), out), n -= 1000;
	if (n >= 900)
		putc(a + ('C' - 'I'), out), putc(a + ('M' - 'I'), out), n -= 900;
	if (n >= 500)
		putc(a + ('D' - 'I'), out), n -= 500;
	if (n >= 400)
		putc(a + ('C' - 'I'), out), putc(a + ('D' - 'I'), out), n -= 400;
	while (n >= 100)
		putc(a + ('C' - 'I'), out), n -= 100;
	if (n >= 90)
		putc(a + ('X' - 'I'), out), putc(a + ('C' - 'I'), out), n -= 90;
	if (n >= 50)
		putc(a + ('L' - 'I'), out), n -= 50;
	if (n >= 40)
		putc(a + ('X' - 'I'), out), putc(a + ('L' - 'I'), out), n -= 40;
	while (n >= 10)
		putc(a + ('X' - 'I'), out), n -= 10;
	if (n >= 9)
		putc(a + ('I' - 'I'), out), putc(a + ('X' - 'I'), out), n -= 9;
	if (n >= 5)
		putc(a + ('V' - 'I'), out), n -= 5;
	if (n >= 4)
		putc(a + ('I' - 'I'), out), putc(a + ('V' - 'I'), out), n -= 4;
	while (n >= 1)
		putc(a + ('I' - 'I'), out), n -= 1;
}
